package com.hzsai.dynamicdatasource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * hzsai 2019/8/28
 * usage: 动态数据源切换
 *
 **/
@Aspect
//@Order(-1) // 序号，越小，优先级越高
@Component
public class DynamicDSAspect {

    private static final Logger LOG = LoggerFactory.getLogger(DynamicDSAspect.class);

    @Pointcut("execution(* com.hzsai.mappersc.*.*(..))")
    public void pointCut(){}

    /**
     * 下面的两个Before的执行顺序：
     * 1. @Before("@annotation(ds)")
     * 2. @Before("pointCut()")
     * 所以，可以认为，它是按照`顺序`来实现执行的（看使用的地方）
     *
     * 从DynamicDSController来的调用顺序：
     * DynamicDSController-> selectUserPage -> DynamicDSService-> @DynamicDS->selectUserPage -> AopUsermapper->selectUserPage
     */

    /**
     * 拦截的是注解
     * 执行方法前设置数据源
     * @param point 切点
     * @param ds 目标数据源
     */
    @Before("@annotation(ds)")
    public void before(JoinPoint point, DynamicDS ds) {

        DataSourceKey key = ds.datasourceKey();
        LOG.debug("切换数据源为 {}", key);
        DataSourceContextHolder.setDB(key);
    }

    /**
     * 执行方法收清楚数据源
     * @param point
     * @param ds 目标数据源
     */
    @After("@annotation(ds)")
    public void after(JoinPoint point, DynamicDS ds) {

        System.out.println("After DS changes.");

        LOG.debug("移除数据源 {}", ds.datasourceKey());
        DataSourceContextHolder.clear();
    }

    /**
     * pointCut拦截的是mappersc包下面的所有类的所有方法
     * @param joinPoint
     */
//    @Before("pointCut()")
//    public void doBefore(JoinPoint joinPoint) {
//
//        System.out.println("遭遇[切点pointCut()]中...");
//
//        // 获取当前切点签名
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        // 获取当前切点对象
//        Method method = signature.getMethod();
//
//        // 切点对象的类是接口？？？
//        // 我不知道这是在干什么，，，
//        if (method.getDeclaringClass().isInterface()) {
//            try {
//                method = joinPoint.getTarget().getClass()
//                        .getDeclaredMethod(joinPoint.getSignature().getName(), method.getParameterTypes());
//            } catch (NoSuchMethodException e) {
//                e.printStackTrace();
//                LOG.error("方法不存在？？？", e);
//            }
//        }
//
//        if (null == method.getAnnotation(DynamicDS.class)) {
//            // 这个被捕获的方法没有被DynamicDS标注，使用默认的数据源
//            DataSourceContextHolder.setDB(DataSourceKey.THIRD);
//        }
//    }

    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("After DS returning.");
    }
}
